package me.wangcai.onlinechat.controller;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.SneakyThrows;
import me.wangcai.onlinechat.config.GetHttpSessionConfigurator;
import me.wangcai.onlinechat.model.message.Message;
import me.wangcai.onlinechat.model.User;
import me.wangcai.onlinechat.model.message.MessageTag;
import me.wangcai.onlinechat.model.message.OnlineList;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@ServerEndpoint(value = "/connect",configurator= GetHttpSessionConfigurator.class)
@Component
public class ChatServer {

    private static final Gson gson = new Gson();

    //在线用户
    private static final HashMap<Session, User> sessionMap = new HashMap<>();

    //聊天记录
    private static final List<Message> chatRecord = new ArrayList<>();

    //刚刚下线的用户,检测有没有马上重连,如果马上重连则不发送上线提示
    private static final List<HttpSession> lastOffline = new ArrayList<>();


    private Session session;
    private EndpointConfig config;

    @SneakyThrows
    @OnOpen
    public void onOpen(Session session, EndpointConfig config){
        this.session = session;
        this.config = config;
        HttpSession httpSession = getHttpSession();
        User user = (User) httpSession.getAttribute("user");
        if(user == null) {
            session.close();
            return;
        }
        for (Session session1 : sessionMap.keySet()) {
            User user1 = sessionMap.get(session1);
            if(user1.getUsername().equals(user.getUsername())){
                user1.offline();
                session1.close();
                break;
            }
        }
        sessionMap.put(session,user);
        sendMessage(new Message(MessageTag.USERNAME,user.getUsername(),user.getUsername()));
        sendOnlineUser();
        sendChatRecord(10);
        if(!lastOffline.contains(httpSession)){
            sendTips(user.getUsername() + "进入了聊天室!");
        }
        lastOffline.remove(httpSession);
    }

    @OnClose
    public void onClose(Session session){
        User user = sessionMap.get(session);
        sessionMap.remove(session);

        /*
        检测断线重连
         */
        HttpSession httpsession = getHttpSession();
        if(!lastOffline.contains(httpsession)){
            new Thread(() -> {
                lastOffline.add(httpsession);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(lastOffline.contains(httpsession)) sendTips(user.getUsername() + "退出了聊天室!");
                lastOffline.remove(httpsession);
            }).start();
        }

        sendOnlineUser();
    }

    @SneakyThrows
    @OnMessage
    public void onMessage(String messageStr) {
        Message message = gson.fromJson(messageStr, Message.class);
        HttpSession httpSession = getHttpSession();
        User user = (User) httpSession.getAttribute("user");
        if(user == null) {
            session.close();
            return;
        }
        if(message.getTag() == MessageTag.TEXT){
            message = new Message(MessageTag.TEXT,message.getUsername(),message.getMessage());
            sendAllMessage(message);
            chatRecord.add(message);
            return;
        }
        if(message.getTag() == MessageTag.IMAGE){
            message = new Message(MessageTag.IMAGE,message.getUsername(),message.getMessage());
            sendAllMessage(message);
            chatRecord.add(message);
        }
    }

    private void sendAllMessage(Message message){
        for (Session session : sessionMap.keySet()) {
            try {
                session.getBasicRemote().sendText(gson.toJson(message));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @SneakyThrows
    private void sendMessage(Message message){
        session.getBasicRemote().sendText(gson.toJson(message));
    }

    private HttpSession getHttpSession(){
        return  (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
    }

    private void sendChatRecord(int amount){
        if(chatRecord.size() < amount) amount = chatRecord.size();
        for (int i = chatRecord.size() - amount; i < chatRecord.size(); i++) {
            sendMessage(chatRecord.get(i));
        }
    }

    private void sendOnlineUser(){
        sendAllMessage(new Message(MessageTag.ONLINELIST,null,gson.toJson(new OnlineList(new ArrayList<>(sessionMap.values())))));
    }

    private void sendTips(String msg){
        Message message = new Message(MessageTag.TIPS, null, msg);
        chatRecord.add(message);
        sendAllMessage(message);
    }
}

